package de.uni.bremen.estudent.lbs.provider;


import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


/**
 * SQL-Lite OpenHelper for the eStudentLBS Database.
 * 
 * @author bahlfeld
 * @version 1.0 29.02.2012
 */
public final class EstudentLBSDatabase extends SQLiteOpenHelper {

    /**
     * Interface represents the database-table names.
     * 
     * @author bahlfeld
     * @version 1.0 29.02.2012
     */
    interface Tables {
        /**
         * Name of the categorie table.
         */
        String CATEGORIES = "categories";
        /**
         * Name of the meal table.
         */
        String MEALS = "meals";
        /**
         * Name of the pois-table
         */
        String POIS = "pois";
    }

    /**
     * Size of the byte array.
     */
    private static final int BYTE_ARRAY_SIZE = 1024;
    /**
     * Database name.
     */
    private static final String DB_NAME = "lbs_db.sqlite";
    /**
     * path to the database.
     */
    private static final String DB_PATH = "/data/data/de.uni.bremen.estudent.lbs/databases/";

    /**
     * Database version.
     */
    private static final int DB_VERSION = 1;
    /**
     * Class tag.
     */
    private static final String TAG = "eStudentLBSDatabase";
    /**
     * context.
     */
    private final Context mContext;
    /**
     * Database object.
     */
    private SQLiteDatabase myDatabase;

    /**
     * Constructor of the class.
     * 
     * @param context APP-Context.
     */
    public EstudentLBSDatabase(final Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        mContext = context;
    }

    @Override
    public synchronized void close() {
        if (myDatabase != null) {
            myDatabase.close();
        }
        super.close();
    }

    /**
     * Creats the database.
     * 
     * @throws IOException throws an IOException when it is not possible to read
     *         the database file.
     */
    public void createDataBase() throws IOException {
        boolean dbExist = checkDB();

        if (dbExist) {
            // do nothing...
        } else {
            this.getReadableDatabase();
            try {
                copyDataBase();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
                throw new Error("Error copying database.");
            }
        }
    }

    /**
     * Returns the database object.
     * 
     * @return The database object.
     */
    public SQLiteDatabase getDb() {
        try {
            return getWritableDatabase();
        } catch (SQLException e) {
            Log.e(TAG, e.getMessage());
            return getReadableDatabase();
        }
    }

    @Override
    public void onCreate(final SQLiteDatabase arg0) {
    }

    @Override
    public void onUpgrade(final SQLiteDatabase arg0, final int arg1,
                          final int arg2) {
        // TODO Auto-generated method stub

    }

    /**
     * Opens the database.
     */
    public void openDataBase() {

        final String path = DB_PATH + DB_NAME;
        myDatabase = SQLiteDatabase.openDatabase(path, null,
                                                 SQLiteDatabase.OPEN_READONLY);
    }

    /**
     * Checks if a database already exists.
     * 
     * @return Return true if a database exists else false.
     */
    private boolean checkDB() {
        SQLiteDatabase db = null;
        try {
            // Try to open the database with.
            final String dbPath = DB_PATH + DB_NAME;
            db = SQLiteDatabase.openDatabase(dbPath, null,
                                             SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            // Fails...database doesn't exists.
            Log.e(TAG, e.getMessage() + "DB not exist.");
        }

        if (db != null) {
            db.close();
            return true;
        } else {
            return false;
        }
    }

    /**
     * Copies the database from the assetfolder to the database folder so it can
     * be used by the app.
     * 
     * @throws IOException Throws IOException when file not exist or not able to
     *         read.
     */
    private void copyDataBase() throws IOException {
        InputStream input = mContext.getAssets().open(DB_NAME);

        final String outputFileName = DB_PATH + DB_NAME;

        OutputStream output = new FileOutputStream(outputFileName);

        byte[] buffer = new byte[BYTE_ARRAY_SIZE];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        input.close();

    }

}
